﻿using System;
using System.Collections.Generic;
using System.Text;
using Castle.Services.Transaction;
using MiragePWF.NH.Logging;
using MiragePWF.NH.Repositories;
using NHibernate.Criterion;
using Wolfut.MirageEE.Domain.Common;
using Wolfut.MirageEE.Domain.CommonUtilities;
using Wolfut.MirageEE.Interface.Common;
using Wolfut.MirageEE.Kernal.Common;

namespace Wolfut.MirageEE.Server.Server.Common
{
    [Transactional]
    [AutoLogging]
    public class CodeRulesService : BusinessServiceBase,ICodeRulesService
    {
        private static object lockObj = new object();
        private readonly IRepository<CodeRule> codeRuleRepository;
        public CodeRulesService(IRepository<CodeRule> codeRuleRepository)
        {
            this.codeRuleRepository = codeRuleRepository;
        }
        /// <summary>
        /// 增加一个编码规则
        /// </summary>
        /// <param name="coderule"></param>
        /// <returns></returns>
        [Transaction(TransactionMode.Requires)]
        public CodeRule AddOrUpdateCodeRule(CodeRule item)
        {
            //item.LastCode = String.Empty;
            codeRuleRepository.Save(item);
            if (item.IsDefault)
            {
                IList<CodeRule> listItems = this.ListCodeRulesByCodeFlag(item.CodeFlag, false);
                listItems.Remove(item);
                foreach (CodeRule listItem in listItems)
                {
                    listItem.IsDefault = false;
                    codeRuleRepository.Save(listItem);
                }
            }
            return item;
        }        

        public CodeRule GetCodeRuleByID(String codeRuleID)
        {
            return codeRuleRepository.Find(codeRuleID);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="codePrefix"></param>
        /// <returns></returns>
        public CodeRule GetCodeRuleByCodePrefix(String codePrefix)
        {
            return codeRuleRepository.FindFirst(Restrictions.Eq("CodePre", codePrefix));
        }

        public IList<CodeRule> ListCodeRulesByCodeFlag(String codeFlag, bool isDeleted)
        {
            DetachedCriteria criteria = DetachedCriteria.For(typeof(CodeRule));
            if (!String.IsNullOrEmpty(codeFlag))
            {
                criteria.Add(Expression.Eq("CodeFlag", codeFlag));
            }
            criteria.Add(Expression.Eq("IsDeleted", isDeleted));
            criteria.AddOrder(new Order("IsDefault", false));
            criteria.AddOrder(new Order("CodePre", true));
            return codeRuleRepository.FindAll(criteria);
        }

        private String ToLengthString(Int64  no, int Width)
        {
            StringBuilder strCode = new StringBuilder();
            for (int ii = 0; ii < Width - no.ToString().Length; ii++)
            {
                strCode.Append("0");
            }
            strCode.Append(no.ToString());
            return strCode.ToString();
        }
        public String GenerateCodeRuleByCodePre(String CodePre)
        {            
            lock (lockObj)
            {                
                if (String.IsNullOrEmpty(CodePre))
                {
                    return String.Empty;
                }
                CodeRule item = this.GetCodeRuleByCodePrefix(CodePre);
                                
                    #region 第一次生成代码
                    StringBuilder strCodeRule = new StringBuilder();
                    if (!String.IsNullOrEmpty(item.CodePre))
                    {
                        strCodeRule.Append(item.CodePre);
                    }
                    
                    switch (item.CodeManner)
                    {
                        case CodeManner.YearManner:
                            if (item.YearWidth == 4)
                            {                               
                                strCodeRule.Append(DateTime.Today.ToString("yyyy"));
                            }
                            else
                            {
                                strCodeRule.Append(DateTime.Today.ToString("yy"));
                            }
                            break;
                        case CodeManner.MonthManner:
                            if (item.YearWidth == 4)
                            {
                                strCodeRule.Append(DateTime.Today.ToString("yyyyMM"));
                            }
                            else
                            {
                                strCodeRule.Append(DateTime.Today.ToString("yyMM"));
                            }
                            break;
                        case CodeManner.DayManner:
                            if (item.YearWidth == 4)
                            {
                                strCodeRule.Append(DateTime.Today.ToString("yyyyMMdd"));
                            }
                            else
                            {
                                strCodeRule.Append(DateTime.Today.ToString("yyMMdd"));
                            }
                            break;
                        default:
                            break;
                    }
                    #endregion

                    if (String.IsNullOrEmpty(item.LastCode))
                    {                        
                        strCodeRule.Append(this.ToLengthString(item.StartNo, item.RuleWidth));                        
                    }
                    else
                    {
                        String autoCode = item.LastCode.Substring(item.LastCode.Length - item.RuleWidth,item.RuleWidth);                        
                        Int64 no = Convert.ToInt64(autoCode);
                        no += 1;
                        //采番满了之后处理
                        if (no.ToString().Length > item.RuleWidth)
                        {
                            strCodeRule.Append(this.ToLengthString(item.StartNo, item.RuleWidth)); 
                        }
                        else
                        {
                            strCodeRule.Append(this.ToLengthString(no, item.RuleWidth)); 
                        }
                    }
                    item.LastCode = strCodeRule.ToString();
                    this.AddOrUpdateCodeRule(item);
                    return item.LastCode;
            }
        }
    }
}